<template>
  <FormItem v-bind="formItemProps" :rules="computeRules" :disabled="inputDisabled">
    <template #default>
      <ElSelect
        :value="value"
        :filterable="filterable"
        :placeholder="inputDisabled ? '--' : computePlaceholder"
        v-bind="inputProps"
        :disabled="inputDisabled"
        clearable
        v-on="listeners"
        @input="emitInput">
        <slot>
          <ElOption v-for="item in innerOptions" :key="item[valueKey]" :value="item[valueKey]" :label="item[labelKey]" />
        </slot>
      </ElSelect>
      <div v-if="$slots.warn" class="el-form-item__warn">
        <slot name="warn"></slot>
      </div>
    </template>
    <template #error="{ error }">
      <div v-if="$scopedSlots.error && $scopedSlots.error(error)" class="el-form-item__error">
        <slot name="error" :error="error">{{ error }}</slot>
      </div>
    </template>
    <template #label>
      <slot name="label"></slot>
    </template>
    <template #below>
      <slot name="below"></slot>
    </template>
  </FormItem>
</template>

<script>
  import formInput from './form-input'
  import formPick from '@/components/form/form-pick'
  import dictionary from '@/vue/mixin/dictionary'
  import { Select } from 'element-ui'
  import { filterProperties, normalizeProps } from '@/util'

  const autoBindKeys = Object.keys(Select.props).filter(key => !['value', 'placeholder', 'disabled'].includes(key))

  export default {
    name: 'FormSelect',
    mixins: [formInput, formPick, dictionary],
    props: {
      options: {
        type: Array,
        default: () => []
      },
      gender: Boolean,
      all: Boolean,
      filterable: Boolean,
      confirm: Boolean,
      start: Number,
      end: Number,
      value: [String, Number, Array],
      optionLabel: [String, Number],
      labelProp: {
        type: String,
        default: 'name'
      },
      valueProp: {
        type: String,
        default: 'code'
      },
      emitLabel: Boolean,
      english: Boolean,
      chinese: Boolean,
      typing: Boolean,
      legacy: Boolean
    },
    computed: {
      prefix() {
        return '请选择'
      },
      labelKey() {
        return this.legacy ? this.labelProp : 'label'
      },
      valueKey() {
        return this.legacy ? this.valueProp : 'value'
      },
      inputProps() {
        return filterProperties({ ...normalizeProps(this.$attrs), ...this.$props }, autoBindKeys)
      },
      innerOptions() {
        if (this.dictType) {
          return this.dictItems
        }
        if (this.gender) {
          return [
            {
              [this.labelKey]: '男',
              [this.valueKey]: this.chinese ? '男' : this.typing ? 1 : '1'
            },
            {
              [this.labelKey]: '女',
              [this.valueKey]: this.chinese ? '女' : this.typing ? 2 : '2'
            }
          ]
        }
        if (this.confirm) {
          return [
            {
              [this.labelKey]: '是',
              [this.valueKey]: this.chinese ? '是' : this.english ? 'Y' : this.typing ? 1 : '1'
            },
            {
              [this.labelKey]: '否',
              [this.valueKey]: this.chinese ? '否' : this.english ? 'N' : this.typing ? 0 : '0'
            }
          ]
        }
        if (this.all) {
          return [{ [this.valueKey]: '', [this.labelKey]: '全部' }, ...this.options]
        }

        if (this.start && this.end) {
          return Array(this.end - this.start + 1)
            .fill(1)
            .map((value, index) => {
              return {
                [this.labelKey]: this.start + index,
                [this.valueKey]: this.start + index
              }
            })
        }
        return this.options
      }
    },
    methods: {
      emitInput(val) {
        this.$emit('input', val)
        if (this.emitLabel) {
          const option = this.innerOptions.find(value => value[this.valueKey] === val)
          const newLabel = option?.[this.labelKey]
          if (newLabel !== this.optionLabel) {
            this.$emit('update:optionLabel', newLabel)
          }
        }
      }
    }
  }
</script>

<style lang="scss">
  .el-select {
    width: 100%;
  }
</style>
